package com.nlx.notes.module.service.impl.statistics;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.nlx.notes.module.bean.bo.TransactionsBO;
import com.nlx.notes.module.bean.dto.querydb.FlowMonthQueryDbDTO;
import com.nlx.notes.module.bean.dto.querydb.StatisticsQueryDTO;
import com.nlx.notes.module.bean.dto.statistics.TopStatisticsDBQueryDTO;
import com.nlx.notes.module.bean.dto.statistics.TopStatisticsDTO;
import com.nlx.notes.module.bean.dto.statistics.YearMonthStatisticsQueryDTO;
import com.nlx.notes.module.bean.dto.statistics.YearOverviewQueryDTO;
import com.nlx.notes.module.bean.vo.charts.ChartsDataVO;
import com.nlx.notes.module.bean.vo.charts.MonthChartsDataVO;
import com.nlx.notes.module.bean.vo.statistics.*;
import com.nlx.notes.module.core.consts.GlobalConst;
import com.nlx.notes.module.core.enums.TransactionTypeEnum;
import com.nlx.notes.module.core.enums.error.FlowCodeEnum;
import com.nlx.notes.module.core.enums.error.StatisticsCodeEnum;
import com.nlx.notes.module.core.util.AmountConverterUtils;
import com.nlx.notes.module.core.util.DateUtils;
import com.nlx.notes.module.entity.FlowMonthStatistics;
import com.nlx.notes.module.entity.FlowYearStatistics;
import com.nlx.notes.module.service.IFlowMonthStatisticsService;
import com.nlx.notes.module.service.IFlowYearStatisticsService;
import com.nlx.notes.module.service.ITransactionsService;
import com.nlx.notes.module.service.charts.FlowChartsService;
import com.nlx.notes.module.service.statistics.CategoryMonthStatisticsManageService;
import com.nlx.notes.module.service.statistics.StatisticsManageService;
import com.nlx.notes.support.context.UserHolder;
import com.nlx.notes.support.handler.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class StatisticsManageServiceImpl implements StatisticsManageService {

    final IFlowMonthStatisticsService flowMonthStatisticsService;

    final ITransactionsService transactionsService;

    final CategoryMonthStatisticsManageService categoryMonthStatisticsManageService;

    final FlowChartsService flowChartsService;

    final IFlowYearStatisticsService flowYearStatisticsService;



    @Override
    public MonthStatisticsVO monthOverview(StatisticsQueryDTO statisticsQueryDTO) {
        String month = statisticsQueryDTO.getMonth();
        if(StrUtil.isEmpty(month)){
            month = DateUtils.formatCurrentMonth();
        }
        MonthStatisticsVO monthStatisticsVO = new MonthStatisticsVO(month);
        FlowMonthStatistics monthStatistics = flowMonthStatisticsService.findByMonth(month, statisticsQueryDTO.getBookId(),statisticsQueryDTO.getUserId());
        if(null == monthStatistics){
            log.error("没有找到当前用户 {} 的月度 {} 概览", month, statisticsQueryDTO.getUserId());
            return monthStatisticsVO;
        }
        monthStatisticsVO.setExpenseAmount(AmountConverterUtils.convertFenToYuan(monthStatistics.getExpense()));
        monthStatisticsVO.setIncomeAmount(AmountConverterUtils.convertFenToYuan(monthStatistics.getIncome()));
        int balanceInt = monthStatistics.getIncome() - monthStatistics.getExpense();
        monthStatisticsVO.setBalance( AmountConverterUtils.convertFenToYuan(balanceInt) );
        return monthStatisticsVO;
    }

    @Override
    public List<TopStatisticsVO> topStatistics(TopStatisticsDTO topStatisticsDTO) {
        String flowType;
        if(TransactionTypeEnum.EXPEND.getCode().equalsIgnoreCase(topStatisticsDTO.getType())){
            flowType = TransactionTypeEnum.EXPEND.getCode();
        }else if(TransactionTypeEnum.INCOME.getCode().equalsIgnoreCase(topStatisticsDTO.getType())){
            flowType = TransactionTypeEnum.INCOME.getCode();
        }else{
            log.error("flow type {} not support", topStatisticsDTO.getType());
            throw new BusinessException(FlowCodeEnum.FLOW_TYPE_NOT_SUPPORTED);
        }
        String startDate;
        String endDate;
        TopStatisticsDBQueryDTO topStatisticsDBQueryDTO = new TopStatisticsDBQueryDTO();
        if(GlobalConst.Date.DATE_TYPE_MONTH.equalsIgnoreCase(topStatisticsDTO.getDateType())){
            YearMonth monthDate = DateUtils.parseMonthDate(topStatisticsDTO.getDate());
            startDate = DateUtils.formatFirstDayFortMonth(monthDate);
            endDate = DateUtils.formatLastDayForMonth(monthDate);
            topStatisticsDBQueryDTO.setTopLimit(5);
        }else if(GlobalConst.Date.DATE_TYPE_YEAR.equalsIgnoreCase(topStatisticsDTO.getDateType())){
            LocalDate yearDate = DateUtils.parseYearDate(topStatisticsDTO.getDate());
            startDate = DateUtils.formatFirstDayFortYear(yearDate);
            endDate = DateUtils.formatLastDayForYear(yearDate);
            topStatisticsDBQueryDTO.setTopLimit(20);
        }else{
            log.error("date type {} not support", topStatisticsDTO.getDateType());
            throw new BusinessException(FlowCodeEnum.FLOW_DATE_TYPE_NOT_SUPPORTED);
        }
        topStatisticsDBQueryDTO.setType(flowType);
        topStatisticsDBQueryDTO.setStartDate(startDate);
        topStatisticsDBQueryDTO.setEndDate(endDate);
        topStatisticsDBQueryDTO.setUserId(topStatisticsDTO.getUserId());
        topStatisticsDBQueryDTO.setBookId(topStatisticsDTO.getBookId());
        List<TransactionsBO> transactionsBOList = this.transactionsService.findTop(topStatisticsDBQueryDTO);
        if(CollUtil.isEmpty(transactionsBOList)){
            return Collections.emptyList();
        }
        List<TopStatisticsVO> topStatisticsVOList = new ArrayList<>();
        for(TransactionsBO transaction : transactionsBOList){
            TopStatisticsVO topStatisticsVO = new TopStatisticsVO();
            topStatisticsVO.setFlowId(transaction.getId());
            topStatisticsVO.setCategoryName(transaction.getSecondCategoryName());
            topStatisticsVO.setFlowDesc(transaction.getDescription());
            topStatisticsVO.setFlowDate(transaction.getTransactionDate());
            topStatisticsVO.setAmount(AmountConverterUtils.convertFenToYuan(transaction.getAmount()));
            topStatisticsVOList.add(topStatisticsVO);
        }
        return topStatisticsVOList;
    }

    @Override
    public MonthChartsDataVO monthStatisticsMetrics(YearMonth month, Long userId,Long bookId) {
        MonthChartsDataVO monthChartsDataVO = new MonthChartsDataVO();
        if(null == month){
            month = YearMonth.now();
        }
        String monthStr = DateUtils.formatMonth(month);
        //查询月度的总收支情况
        FlowMonthStatistics monthStatistics = flowMonthStatisticsService.findByMonth(monthStr,bookId, userId);
        if(null == monthStatistics){
            return monthChartsDataVO;
        }
        MonthStatisticsVO monthStatisticsVO = new MonthStatisticsVO();
        monthStatisticsVO.setMonthDate(monthStatistics.getMonthTime());
        monthStatisticsVO.setExpenseAmount(AmountConverterUtils.convertFenToYuan(monthStatistics.getExpense()));
        monthStatisticsVO.setIncomeAmount(AmountConverterUtils.convertFenToYuan(monthStatistics.getIncome()));
        monthStatisticsVO.setBalance(AmountConverterUtils.convertFenToYuan(monthStatistics.getIncome() - monthStatistics.getExpense() ));
        monthChartsDataVO.setMonthStatistics(monthStatisticsVO);
        //查询月度的每天收支情况
        List<ChartsDataVO> chartsDataVOS = flowChartsService.dayCharts(month,bookId, UserHolder.getUserContext().getId());
        for (ChartsDataVO chartsDataVO: chartsDataVOS){
            if(StrUtil.isNotEmpty(chartsDataVO.getDate())){
                chartsDataVO.setDate(chartsDataVO.getDate().split("-")[2]);
            }
        }
        monthChartsDataVO.setMonthChartsDataList(chartsDataVOS);
        return monthChartsDataVO;
    }

    @Override
    public YearOverviewStatisticsVO yearOverviewStatistics(YearOverviewQueryDTO yearOverviewQueryDTO) {
        if(StrUtil.isEmpty(yearOverviewQueryDTO.getYear())){
            throw new BusinessException(StatisticsCodeEnum.PLEASE_CHOOSE_YEAR_ERROR);
        }
        YearOverviewStatisticsVO yearOverviewStatisticsVO = new YearOverviewStatisticsVO();
        FlowYearStatistics flowYearStatistics = flowYearStatisticsService.findByYear(yearOverviewQueryDTO.getYear(), yearOverviewQueryDTO.getBookId(),yearOverviewQueryDTO.getUserId());
        if(null != flowYearStatistics){
            yearOverviewStatisticsVO.setTotalExpense(AmountConverterUtils.convertFenToYuan(flowYearStatistics.getExpense()));
            yearOverviewStatisticsVO.setTotalIncome(AmountConverterUtils.convertFenToYuan(flowYearStatistics.getIncome()));
            yearOverviewStatisticsVO.setTotalBalance(AmountConverterUtils.convertFenToYuan(flowYearStatistics.getIncome() - flowYearStatistics.getExpense()));
            yearOverviewStatisticsVO.setAvgExpense(AmountConverterUtils.convertFenToYuan(flowYearStatistics.getExpense()/12));
            //获取本年消费最高的一个月
            FlowMonthStatistics maxExpense = flowMonthStatisticsService.findMaxAmountByYear(yearOverviewQueryDTO.getYear(), TransactionTypeEnum.EXPEND.getCode(),yearOverviewQueryDTO.getBookId(),yearOverviewQueryDTO.getUserId());
            FlowMonthStatistics maxIncome = flowMonthStatisticsService.findMaxAmountByYear(yearOverviewQueryDTO.getYear(),TransactionTypeEnum.INCOME.getCode(),yearOverviewQueryDTO.getBookId(),yearOverviewQueryDTO.getUserId());
            if(null != maxExpense){
                yearOverviewStatisticsVO.setExpenseHighestAmount(AmountConverterUtils.convertFenToYuan(maxExpense.getExpense()));
                yearOverviewStatisticsVO.setMaxExpenseMonth(DateUtils.yearMonthToMonth(maxExpense.getMonthTime()) );
            }
            if(null != maxIncome){
                yearOverviewStatisticsVO.setIncomeHighestAmount(AmountConverterUtils.convertFenToYuan(maxIncome.getIncome()));
                yearOverviewStatisticsVO.setMaxIncomeMonth( DateUtils.yearMonthToMonth(maxIncome.getMonthTime()));
            }
        }
        return yearOverviewStatisticsVO;
    }

    @Override
    public List<YearMonthStatisticsVO> yearMonthStatistics(YearMonthStatisticsQueryDTO yearMonthStatisticsQueryDTO) {
        // 创建查询条件
        FlowMonthQueryDbDTO flowMonthQueryDbDTO = new FlowMonthQueryDbDTO();
        flowMonthQueryDbDTO.setUserId(yearMonthStatisticsQueryDTO.getUserId());
        flowMonthQueryDbDTO.setYear(yearMonthStatisticsQueryDTO.getYear());
        flowMonthQueryDbDTO.setBookId(yearMonthStatisticsQueryDTO.getBookId());
        // 查询该年份的所有月度统计数据
        List<FlowMonthStatistics> monthStatisticsList = flowMonthStatisticsService.findByCondition(flowMonthQueryDbDTO);
        
        // 创建返回结果列表
        List<YearMonthStatisticsVO> result = new ArrayList<>();
        
        // 初始化12个月的数据
        for (int i = 1; i <= 12; i++) {
            YearMonthStatisticsVO vo = new YearMonthStatisticsVO();
            String month = String.format("%02d", i); // 格式化为两位数的月份
            vo.setMonth(month);
            vo.setMonthName(month);
            vo.setExpenseAmount("0");
            vo.setIncomeAmount("0");
            result.add(vo);
        }
        
        // 填充实际数据
        if (CollUtil.isNotEmpty(monthStatisticsList)) {
            for (FlowMonthStatistics monthStat : monthStatisticsList) {
                // 从monthTime中提取月份，格式为 yyyy-MM
                String monthTime = monthStat.getMonthTime();
                if (StrUtil.isNotEmpty(monthTime) && monthTime.length() >= 7) {
                    String month = monthTime.substring(5, 7); // 提取月份部分
                    int monthIndex = Integer.parseInt(month) - 1; // 转换为索引
                    
                    if (monthIndex >= 0 && monthIndex < 12) {
                        YearMonthStatisticsVO vo = result.get(monthIndex);
                        vo.setExpenseAmount(AmountConverterUtils.convertFenToYuan(monthStat.getExpense()));
                        vo.setIncomeAmount(AmountConverterUtils.convertFenToYuan(monthStat.getIncome()));
                    }
                }
            }
        }
        
        return result;
    }

    @Override
    public UserYearlyStatisticsVO getUserYearlyStatistics(Long userId,Long bookId) {
        // 查询用户的所有年份统计数据
        List<FlowYearStatistics> yearStatisticsList = flowYearStatisticsService.findAllByUserId(userId,bookId);
        
        UserYearlyStatisticsVO result = new UserYearlyStatisticsVO();
        List<YearlyStatisticsDetailVO> detailList = new ArrayList<>();
        
        if (CollUtil.isNotEmpty(yearStatisticsList)) {
            // 用于计算最大最小支出年份
            FlowYearStatistics maxExpenseYearStat = null;
            FlowYearStatistics minExpenseYearStat = null;

            int totalExpense = 0;
            int totalIncome = 0;
            for (FlowYearStatistics yearStat : yearStatisticsList) {
                totalExpense = totalExpense + yearStat.getExpense();
                totalIncome = totalIncome + yearStat.getIncome();
                YearlyStatisticsDetailVO detailVO = new YearlyStatisticsDetailVO();
                detailVO.setYear(yearStat.getYearTime());
                detailVO.setExpense(AmountConverterUtils.convertFenToYuan(yearStat.getExpense()));
                detailVO.setIncome(AmountConverterUtils.convertFenToYuan(yearStat.getIncome()));
                int balance = yearStat.getIncome() - yearStat.getExpense();
                detailVO.setBalance(AmountConverterUtils.convertFenToYuan(balance));
                
                // 计算年度日均支出（一年按365天计算）
                if (yearStat.getExpense() > 0) {
                    BigDecimal dayAvg = BigDecimal.valueOf(yearStat.getExpense())
                            .divide(BigDecimal.valueOf(365), 2, BigDecimal.ROUND_HALF_UP);
                    detailVO.setDayAvg(AmountConverterUtils.convertFenToYuan(dayAvg.intValue()));
                    BigDecimal monthAvg = BigDecimal.valueOf(yearStat.getExpense())
                            .divide(BigDecimal.valueOf(12), 2, BigDecimal.ROUND_HALF_UP);
                    detailVO.setMonthAvg(AmountConverterUtils.convertFenToYuan(monthAvg.intValue()));
                } else {
                    detailVO.setDayAvg("0");
                    detailVO.setMonthAvg("0");
                }
                detailList.add(detailVO);
                
                // 更新最大最小支出年份
                if (maxExpenseYearStat == null || yearStat.getExpense() > maxExpenseYearStat.getExpense()) {
                    maxExpenseYearStat = yearStat;
                }
                if (minExpenseYearStat == null || yearStat.getExpense() < minExpenseYearStat.getExpense()) {
                    minExpenseYearStat = yearStat;
                }
            }
            int totalBalance = totalIncome - totalExpense;
            // 设置最大最小支出年份信息
            if (maxExpenseYearStat != null) {
                result.setMaxExpenseYear(maxExpenseYearStat.getYearTime());
                result.setMaxExpenseVal(AmountConverterUtils.convertFenToYuan(maxExpenseYearStat.getExpense()));
            }
            if (minExpenseYearStat != null) {
                result.setMinExpenseYear(minExpenseYearStat.getYearTime());
                result.setMinExpenseVal(AmountConverterUtils.convertFenToYuan(minExpenseYearStat.getExpense()));
            }
            result.setTotalExpense(AmountConverterUtils.convertFenToYuan(totalExpense));
            result.setTotalIncome(AmountConverterUtils.convertFenToYuan(totalIncome));
            result.setTotalBalance(AmountConverterUtils.convertFenToYuan(totalIncome - totalExpense));


        }
        
        result.setList(detailList);
        return result;
    }
}
